﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using ObligatorioBD.MerObjects;
using Microsoft.SqlServer.Management.Smo;
using System.Threading;

namespace ObligatorioBD.Logic
{
    class DatabaseBuilder
    {
        SqlConnection cnx;
        DatabaseCreator dbCreator;
        string databaseName;
        FKCreator fkCreator;
        MerObjects.Mer mer;
        int totalProg = 1;
        int finalProg = 100;
        string progText = "";
        frmProgress progress;
        public DatabaseBuilder(DatabaseInterface.Connection cnx, string databaseName)
        {
            this.cnx = cnx.getConnection();
            this.databaseName = databaseName;
            this.fkCreator = new FKCreator(cnx, databaseName);
            this.dbCreator = new DatabaseCreator(cnx, databaseName);
        }
        public bool CheckNameAvailability()
        {
            return this.dbCreator.CheckNameAvailability();
        }
        public void BuildDatabaseAsync(MerObjects.Mer mer)
        {
            this.totalProg = 1;
            this.finalProg = mer.GetEntities().Count + mer.GetRelations().Count;
            this.progress = new frmProgress("Creando base de datos", this.finalProg);
            this.mer = mer;
            
            Thread build = new Thread(BuildDatabase);
            Thread prog = new Thread(Progress);

            build.Start();
            //prog.Start();
            build.Join();
            //prog.Join();
            
        }
        private void Progress()
        {
            this.progress.Show();
            while (this.totalProg < finalProg)
            {
                this.progress.Advance(this.progText);
            }
        }
        public void BuildDatabase()
        {
            
            foreach (Entity e in this.mer.GetEntities())
            {
                this.progText = "Creando Tabla " + e.Name;
                this.totalProg++;
                dbCreator.NewTable(e.Name);
                foreach (Atribute a in e.GetAtributes())
                {
                    if (a.Type != Atribute.AtributeType.CompositeType)
                    {
                        dbCreator.AddColumn(a.Name, GetSMOType(a.Type), false, a.IsPrimaryKey);
                    }
                }
                dbCreator.CrateTable();
            }
            Entity referenceEntity = null;
            Entity childEntity = null;
           
            foreach (Relationship r in this.mer.GetRelations())
            {
                this.progText = "Crando relación " + r.Name;
                this.totalProg++;
                foreach (CardinalEntity ce in r.GetEntities())
                {
                    if (ce.Cardinality == "N")
                    {
                        childEntity = ce.Entity;
                    }
                    else
                    {
                        referenceEntity = ce.Entity;
                    }
                }
                this.fkCreator.SelectReferenceTable(referenceEntity.Name, childEntity.Name);
                foreach (Atribute a in referenceEntity.Atributes)
                {
                    if (a.IsPrimaryKey)
                    {
                        this.fkCreator.AddColumnToFK(a.Name);
                    }
                }
                this.fkCreator.CreateForeignKeys();
            }
            this.totalProg++;
                
        }
        private DataType GetSMOType(Atribute.AtributeType atributeType)
        {
            DataType t = new DataType();
            switch (atributeType.ToString().ToUpper())
            {
                case "STRINGTYPE":
                    t = DataType.VarChar(40);
                    break;
                case "DOUBLETYPE":
                    t = DataType.Float;
                    break;
                case "BOOLTYPE":
                    t = DataType.Bit;
                    break;
                case "INTTYPE":
                    t = DataType.Int;
                    break;
            }
            return t;
        }
    }
}
